﻿/*
【说明】
本类为SPH转换器数据读取模块。

【版本】
2022/04/29 初始化创建

【参考资料】
SPH 转换规则文档  https://docs.qq.com/sheet/DWXRVYUtBd251eFVo?u=db936ce54f984d52a53926a39354cc49&tab=va4ty5
XML 读取方法     https://www.cnblogs.com/likui-bookHouse/p/11132756.html
XML 命名空间     https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlnode.selectsinglenode?view=net-6.0
*/

using QDAS;
using QDasConverter.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace QDasConverter.Core
{
    public class C2021T10_SPH : ConvertBase
    {

        /// <summary>
        /// 设置为True，保证一直转换。
        /// </summary>
        /// <returns></returns>
        public override bool NeedConvert() => true;


        DictionaryHelper dh = new DictionaryHelper();

        string TargetDirectory = @"C:\data";
        bool NeedBackup = true;
        bool DeleteSourceAfterConverted = true;
        Dictionary<string, string> ops = new Dictionary<string, string>();

        public C2021T10_SPH()
        {
            NeedConnectionCheck = false;
            DisplayName = "Sciemetric 转换器";
            Version = "beta1 Released Date: 2022/04/29 Inner Name: C2021T10_SPH";
        }



        public override bool OnStart()
        {
            ops.Add("DCT-525", "1109015");
            ops.Add("DCT-530", "1109020");
            dh.Load(GetConfigurefileFullpath(nameof(C2021T10_SPH)) + ".ini");

            // 测试模式使用
            if (DebugMode)
            {
                ProcessDirectory(@"..\..\samples\sph\DCT-525");
            }

            return base.OnStart();
        }

        public override void OneLoop_Prepare()
        {
            if (!Directory.Exists(TargetDirectory))
            {
                Console.WriteLine($"Directory {TargetDirectory} does not exist.");
                return;
            }

            var subdirs = Directory.GetDirectories(TargetDirectory);
            foreach (var subdir in subdirs)
                ProcessDirectory(subdir);
        }


        private void ProcessDirectory(string sphfile_dir)
        {
            // 如果以是 _backup 为后缀名，则是备份文件夹，不用处理
            if (sphfile_dir.ToLower().EndsWith("_backup"))
                return;
            
            // 如果需要备份则创建备份文件夹
            var pathb = sphfile_dir + "_backup"; // 备份文件夹
            if (NeedBackup && !Directory.Exists(pathb))
                Directory.CreateDirectory(pathb);

            // 对文件中的SPH文件进行处理，当前版本只输出终值，不考虑曲线。
            foreach (var sphfile in Directory.GetFiles(sphfile_dir))
            {
                if (!sphfile.ToLower().EndsWith(".sph"))
                    continue;

                XmlDocument root = new XmlDocument();
                root.Load(sphfile);

                XmlNamespaceManager nsm = new XmlNamespaceManager(root.NameTable);
                nsm.AddNamespace("sph", "http://www.sciemetric.com/namespace");

                var K1002 = GetNodeText(root, "descendant::sph:model_number/sph:label", nsm);
                var K0014 = GetNodeText(root, "descendant::sph:serial_number", nsm);

                QFile qf = new QFile();
                qf[1002] = K1002;

                var exclusives = new string[] { "LEVEL", "TEMP" };

                var features = root.SelectNodes("//sph:feature", nsm);
                foreach (XmlNode node in features)
                {
                    var qc = qf.AddQCharacteristic();
                    var K2001 = GetNodeText(node, "descendant::sph:label", nsm);
                    qc[2001] = K2001;
                    qc[2002] = K2001;
                    qc[2110] = GetNodeText(node, "descendant::sph:lower", nsm);
                    qc[2111] = GetNodeText(node, "descendant::sph:upper", nsm);
                    var k2142 = K2001.Contains('_') ? K2001.Split('_')[1] : "";

                    if (!string.IsNullOrEmpty(k2142) && !exclusives.Contains(k2142))
                        qc[2142] = k2142;

                    var K0001 = GetNodeText(node, "descendant::sph:value", nsm);
                    var K0004 = GetNodeText(node, "descendant::sph:date_stamp", nsm);
                    if(!string.IsNullOrEmpty(K0001) && K0004.Contains("T")) // 把带T的换成空格，如 2022-04-19T20:54:49
                        K0004 = K0004.Replace("T", " ");

                    var qdi = qc.AddItem();
                    qdi.SetValue(K0001);
                    qdi.date = DateTime.Parse(K0004);
                    var dirName = GetDirectoryLastName(sphfile_dir);
                    qdi[0010] = ops.ContainsKey(dirName) ? ops[dirName] : "1109000";
                    qdi[0014] = K0014;
                }

                // 保存文件
                qf.ToDMode();
                SaveToDFQ(qf, OutputDirectory, $"C10_{K1002}_{NowString()}.dfq");

                // 文件备份
                if (NeedBackup && Directory.Exists(pathb))
                    CopyFileTo(sphfile, pathb, true);

                // 删除原文件
                if (DeleteSourceAfterConverted)
                    File.Delete(sphfile);
            }
        }

        private string GetDirectoryLastName(string dataPath)
        {
            var dirnames = dataPath.Split('\\');
            return dirnames.Length > 0 ? dirnames[dirnames.Length - 1] : "";
        }

        /// <summary>
        /// 将输入文件移动到指定的目录，文件名不变。
        /// </summary>
        /// <param name="srcfilepath">输入文件。</param>
        /// <param name="targetdir">目标文件夹。</param>
        /// <param name="deleteScr">是否删除原文件，默认值为false。</param>
        /// <param name="deleteTarget">是否删除目标文件，只有目标文件存在时才生效，默认值为true。</param>
        public void CopyFileTo(string srcfilepath, string targetdir, bool deleteScr = false, bool deleteTarget = true)
        {
            // 输出目标的文件名
            var targetFilepath = Path.Combine(targetdir, Path.GetFileName(srcfilepath));

            // 如果目标文件存在且需要删除，则删除目标文件
            if (File.Exists(targetFilepath) && deleteTarget)
                File.Delete(targetFilepath);

            // 在目标文件不存在的情况下才复制
            if (!File.Exists(targetFilepath))
                File.Copy(srcfilepath, targetFilepath);

            // deleteScr决定是否需要删除源文件
            if (deleteScr)
                File.Delete(srcfilepath);
        }

        public override void OneLoop_Completed()
        {
            // ia.WriteValue("lastConvertTime", lastConvertTime.ToString("yyyy-MM-dd HH:mm:ss"));

        }


        public string GetNodeText(XmlNode node, string path, XmlNamespaceManager nsm)
        {
            var n = node.SelectSingleNode(path, nsm);
            return n == null ? "" : n.InnerText;
        }
    }
}
